package com.jeeplus.common.utils.license;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import com.jeeplus.common.utils.license.exception.LicenseInvalidException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;


/**
 * 这个类，在打包的时候，不发布到现场。
 * @author stzhang
 */
public class MyRSAEnCoderTools {
	public final static String licenseFilePath = "C:\\license";
	public final static String licenseFileName = "ESAServer.lic";

	public static boolean checkLicenseFile(String licenseFilePath, String machCode, Date currentDate) throws Exception {
        // 加载证书
		PublicKey publicKey = RSADeCoder.getPublicKey(CryptoPublicKeys.KEYMODULUS, CryptoPublicKeys.PUBLICKEYEXPONENT);
		File licenseFile = new File(licenseFilePath);
		if(!licenseFile.exists()){
			throw new Exception("License文件不存在");
		}
		FileInputStream fis = FileUtils.openInputStream(licenseFile);
		if(fis.available() == 0){
			throw new FileNotFoundException("License加密文件为空");
		}
		fis.close();
		//首先读入License文件
		byte[] encoderData = FileUtils.readFileToByteArray(licenseFile);
		byte[] sbytes = RSADeCoder.decryptRSA(encoderData, publicKey);
		byte[] firstEncoderData = null;
		byte[] secondSignData = null;
		int index =0 ;
		for(int len = sbytes.length; index< len ; index ++ ){
			if(sbytes[index] == '\n'){
				firstEncoderData = new byte[index];
				secondSignData = new byte[len - index - 1];
				//合并两个byte[]
				System.arraycopy(sbytes, 0, firstEncoderData,0, firstEncoderData.length);
				System.arraycopy(sbytes,index + 1, secondSignData, 0 ,secondSignData.length);
				//如果已经是base64编码， 则直接返回
				if(isArrayByteBase64(secondSignData)){
					break;
				}
			}
		}
		String sign = new String(secondSignData);

		boolean verify = RSADeCoder.verify(firstEncoderData, sign, publicKey);
		if(!verify){
			throw new LicenseInvalidException("License签名校验无效,请确认这证书的有效性.");
		}
		//再次解密， 得到最终的授权内容
		byte[] textBytes = RSADeCoder.decryptRSA(firstEncoderData, publicKey);
		// System.out.println("授权文件详情:\n"+new String(textBytes) );
		HashMap<String, String> prop = genDataFromArrayByte(textBytes);
		String licenseType = prop.get("LICENSETYPE");
		if(StringUtils.isEmpty(licenseType)){
			throw new LicenseInvalidException("License校验无效,无法获取证书类型.");
		}

		if(StringUtils.isEmpty(machCode) || !machCode.equals(getMechineCode()) ){
			//--机器码的校验
			throw new LicenseInvalidException("License校验,机器码与当前机器码不同");
		}
		if("1".equals(licenseType) ){//为1时进行时间校验
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
			String expireDay = prop.get("EXPIREDAY");
			Date expireDate = df.parse(expireDay);
			if(currentDate.after(expireDate)){
				throw new LicenseInvalidException("License已经过期,请联系厂商重新获取License授权.");
			}
		}
		//检查数据项：用户数
		// String CLIENTCOUNT = prop.get("CLIENTCOUNT");
		// if(StringUtils.isEmpty(CLIENTCOUNT)){
		// 	throw new LicenseInvalidException("用户数必须填写");
		// }
		//
		// if(!StringUtils.isNumeric(CLIENTCOUNT.trim())){
		// 	throw new LicenseInvalidException("用户数必须为数字");
		// }
		return true;

	}

	public static String getMechineCode(){
		String serial = "";
		try {
			Process process = Runtime.getRuntime().exec(
					new String[] { "wmic", "cpu", "get", "ProcessorId" });
			process.getOutputStream().close();
			Scanner sc = new Scanner(process.getInputStream());
			String property = sc.next();
			serial = sc.next();
			return serial;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return serial;
		}
	}

	public static HashMap<String, String> genDataFromArrayByte(byte[] b) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(new ByteArrayInputStream(b)));
		HashMap<String, String> data = new HashMap<String, String>();
		String str =  null;
		while((str = br.readLine()) != null){
			if(StringUtils.isNotEmpty(str)){
				str = str.trim();
				int pos = str.indexOf("=");
				if(pos <= 0 ) continue;
				if(str.length() > pos + 1){
					data.put(str.substring(0, pos).trim().toUpperCase(), str.substring( pos + 1).trim()) ;
				}else{
					data.put(str.substring(0, pos).trim().toUpperCase(), "") ;
				}
			}
		}
		return data;
	}

	public static boolean isArrayByteBase64(byte[] b){
		try{
			if(Base64.isArrayByteBase64(b)){
				return true;
		    }
			return false;
		}catch(Exception e){//nothing todo
			return false;
		}
	}
 
}
